#ifndef __PROCESS_POOL_HPP__
#define __PROCESS_POOL_HPP__
#include<iostream>
#include<vector>
#include<unistd.h>
#include<cstdlib>
#include<sys/wait.h>
#include"task.hpp"
class channel//管道
{
public:
    channel(int wfd,pid_t gid)
    :_fd(wfd)
    ,_pid(gid)
    {
        _name="channel-"+std::to_string(wfd)+"-"+std::to_string(gid);
    }
    int return_fd()
    {
        return _fd;
    }
    pid_t return_pid()
    {
        return _pid;
    }
    std::string return_name()
    {
        return _name;
    }
    void send(int code)
    {
        int n=write(_fd,&code,sizeof(code));
        (void)n;
    }
    void Close()
    {
        close(_fd);
    }
    void wait()
    {
        pid_t n=waitpid(_pid,nullptr,0);
        (void)n;
    }
    ~channel()
    {

    }
private:
    int _fd;
    pid_t _pid;
    std::string _name;
};
class channelmanager//管道管理
{
public:
    channelmanager()
    :_next(0)
    {}
    void insertchannel(int pipid,pid_t pid)//插入一个新管道
    {
        _as.emplace_back(pipid,pid);
    }
    void printchannelname()
    {
        for(auto& e:_as)
        {
            std::cout<<e.return_name()<<std::endl;
        }
    }
    channel& select()//巡回挑选管道
    {
        auto& c=_as[_next++];
        _next%=_as.size();
        return c;
    }
    void stopprocess()
    {
        for(auto& e:_as)
        {
            e.Close();
            std::cout << "关闭: " << e.return_name() << std::endl;
        }
    }
    void waitprocess()
    {
        for(auto& e:_as)
        {
            e.wait();
            std::cout << "回收: " << e.return_name() << std::endl;
        }
    }
    ~channelmanager()
    {}
private:
    std::vector<channel> _as;
    int _next;
};
const int gdefaultnum = 5;
class processpool//进程池
{
public:
    processpool(int num)
    :_processnum(num)
    {
        _vm.Register(PrintLog);
        _vm.Register(Download);
        _vm.Register(Upload);
    }
    void work(int pipid)
    {
        while(true)
        {
            int code=0; 
            ssize_t n=read(pipid,&code,sizeof(code));
            if(n>0)//子进程读取成功
            {
                if(n!=sizeof(code))//子进程读取不规范
                {
                    continue;
                }
                std::cout << "子进程[" << getpid() << "]收到一个任务码: " << code << std::endl;
                _vm.execute(code);
            }
            else if(n==0)//子进程读取结束并退出
            {
                std::cout << "子进程退出" << std::endl;
                break;
            }
            else//子进程读取失败并退出
            {
                std::cout << "读取错误" << std::endl;
                break;
            }
        }
    }
    bool start()//创建进程池
    {
        for(int i=0;i<_processnum;i++)
        {
            //创建管道
            int cs[2]={0};
            int n=pipe(cs);
            if(n<0)
            {
                return false;
            }
            //创建子进程
            pid_t pid=fork();
            if(pid<0)
            {
                return false;
            }
            else if(pid==0)
            {
                //子进程
                //对于子进程来说，关闭写端
                close(cs[1]);
                 //子进程工作
                work(cs[0]);
                //子进程退出
                close(cs[0]);
                exit(0);
            }
            else
            {
                //父进程
                //对于父进程来说，关闭读端
                close(cs[0]);
                //将子进程pid与写端文件描述符交给管道管理者
                _aq.insertchannel(cs[1],pid);
            }
        }
        return true;
    }
    void debug()
    {
        _aq.printchannelname();
    }
    void run()//运行进程池
    {
        //自动选择任务码
        int code=_vm.code();
        //选择信道
        auto& e=_aq.select();
         std::cout << "选择了一个子进程: " << e.return_name() << std::endl;
        //发送任务
        e.send(code);
        std::cout << "发送了一个任务码: " << code << std::endl;
    }
    void stop()
    {
        //关闭所有父进程的写端
        _aq.stopprocess();
        //回收所有子进程
        _aq.waitprocess();
    }
    ~processpool()
    {
    }
private:
    channelmanager _aq;
    size_t _processnum;
    taskmanager _vm;
};
#endif